package controller

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"image"
	"math"
	"mygo/app/tools"
	"os"
	"strings"
	"time"
)

type SmCtl struct {
}

var Sm = SmCtl{}

func (ctl *SmCtl) GetPngListByDay(c *gin.Context) {
	t := c.Query("time")
	name := c.Query("type")
	dir := c.Query("dir")
	rootPath := "./public/" + dir + "/" + name + "/" + t
	fmt.Println(rootPath)
	//	获得文件夹下所有文件名，直接遍历
	fileNames, err := os.ReadDir(rootPath)
	if err != nil {
		c.JSON(200, gin.H{
			"code":    500,
			"message": "当前日期暂无数据",
		})
		return
	}
	var files []string
	for _, v := range fileNames {
		files = append(files, v.Name())
	}
	c.JSON(200, gin.H{
		"code":    200,
		"message": "success",
		"data":    files,
	})
}

type TestReq struct {
	StartDate string `json:"startDate"`
	EndDate   string `json:"endDate"`
	Type      string `json:"type"`
	Latitude  string `json:"latitude"`
	Longitude string `json:"longitude"`
}
type Range struct {
	StartLon float64 `json:"startLon"`
	EndLon   float64 `json:"endLon"`
	StartLat float64 `json:"startLat"`
	EndLat   float64 `json:"endLat"`
	Uscale   float64 `json:"uscale"`
	Vscale   float64 `json:"vscale"`
	Code     string  `json:"name"`
}

var typeMap = map[string]string{
	"wave": "ww3",
}

var rangeMap = map[string]Range{
	"wave": {
		StartLon: 114.8,
		EndLon:   134.0,
		StartLat: 41.0,
		EndLat:   16.4,
		Uscale:   0.0192,
		Vscale:   0.0246,
		Code:     "ww3",
	},
	"wind": {
		StartLon: 110.13320923,
		EndLon:   134.22895813,
		StartLat: 42.43424988,
		EndLat:   11.55631256,
		Uscale:   0.2077219732758621,
		Vscale:   0.1816349254117647,
		Code:     "wind",
	},
	"tide": {
		StartLon: 120.4,
		EndLon:   122,
		StartLat: 28.4,
		EndLat:   27,
		Uscale:   0.0016,
		Vscale:   0.0014,
		Code:     "tide",
	},
	"current": {
		StartLon: 120.4,
		EndLon:   122,
		StartLat: 28.4,
		EndLat:   27,
		Uscale:   0.0016,
		Vscale:   0.0014,
		Code:     "current",
	},
}

// getTimeSeq 获取时间序列
func (ctl *SmCtl) GetTimeSeq(c *gin.Context) {
	var err error
	var req TestReq
	err = c.ShouldBind(&req)
	if err != nil {
		fmt.Println(err)
		return
	}
	var result []any
	//如果rangeMap中没有对应的type，直接返回
	if _, ok := rangeMap[req.Type]; !ok {
		c.JSON(200, gin.H{
			"message": "pong",
			"data": gin.H{
				req.Type + "DataList": result,
			},
		})
		return
	}
	latInt := tools.StrToFloat64(req.Latitude)
	lonInt := tools.StrToFloat64(req.Longitude)
	fileDir := "C:\\Users\\chun\\Desktop\\Go\\zdbzmb-go\\public\\img\\" + req.Type + "\\"
	StartUnix := timeToUnix(req.StartDate)
	EndUnix := timeToUnix(req.EndDate)
	for i := StartUnix; i <= EndUnix; i += 3600 {
		tm := time.Unix(i, 0)
		tDay := strings.Split(tm.Format("20060102 15"), " ")[0]
		tHour := strings.Split(tm.Format("20060102 15"), " ")[1]
		fileName := fileDir + tDay + "\\" + rangeMap[req.Type].Code + "." + tHour + ".png"
		if !PathExists(fileName) {
			result = append(result, 0)
			continue
		}
		row := int((rangeMap[req.Type].StartLat - latInt) / rangeMap[req.Type].Vscale)
		col := int((lonInt - rangeMap[req.Type].StartLon) / rangeMap[req.Type].Uscale)
		rColor, gColor, bColor := getRgb(fileName, row, col)

		rFloat := float64(rColor)
		gFloat := float64(gColor)
		bFloat := float64(bColor)
		if req.Type == "wave" {
			result = append(result, []any{rFloat + gFloat/100, int(360 * bFloat / 255)})
		} else if req.Type == "tide" {
			result = append(result, (rFloat+gFloat/100+bFloat/10000)*100)
		} else if req.Type == "wind" {
			u := rFloat / 10
			v := gFloat / 10
			if bFloat >= 10 {
				u = -u
			}
			if int(bFloat)%10 == 1 {
				v = -v
			}
			fmt.Println("u:", u, "v:", v)

			value, angle := computeWindUV(u, v)
			fmt.Println("value:", value, "angle:", angle)
			result = append(result, []any{value, angle})
		} else if req.Type == "current" {

		}
	}
	c.JSON(200, gin.H{
		"message": "pong",
		"data": gin.H{
			req.Type + "DataList": result,
		},
	})
}

func getRgb(filePath string, i, j int) (r, g, b uint32) {
	f1, _ := os.Open(filePath)
	defer f1.Close()
	img1, _, _ := image.Decode(f1)
	r, g, b, _ = img1.At(j, i).RGBA()
	r = uint32(float64(r) / 257)
	g = uint32(float64(g) / 257)
	b = uint32(float64(b) / 257)
	return
}

// timeToUnix
func timeToUnix(timeStr string) int64 {
	loc, _ := time.LoadLocation("Local") //获取时区
	tm, _ := time.ParseInLocation("2006-01-02 15:04", timeStr, loc)
	return tm.Unix()
}

// 判断一个文件或文件夹是否存在
func PathExists(path string) bool {
	_, err := os.Stat(path)
	if err != nil {
		if os.IsExist(err) {
			return true
		}
		return false
	}

	return true
}

//  /**转换风场UV值 */
//  computeWindUV: function (u_value, v_value) {
//    let value = Math.sqrt(u_value * u_value + v_value * v_value);
//    let angle = Math.acos(u_value / value);
//    if (v_value < 0) {
//      angle = -angle;
//    }
//    angle = Math.round(angle / Math.PI * 180.0 + 90);
//    if (angle < 0) {
//      angle = angle + 360;
//    }
//    angle = Math.round(360 - angle);
//    value = value.toFixed(1);
//    return {
//      value: parseFloat(value),
//      angle: angle
//    };
//  },

func computeWindUV(uValue, vValue float64) (value, angle float64) {
	value = float64(tools.Round(math.Sqrt(uValue*uValue + vValue*vValue)))
	angle = float64(tools.Round(math.Acos(uValue/value)/3.1415*180.0 + 90))
	if vValue < 0 {
		angle = -angle
	}
	if angle < 0 {
		angle = angle + 360
	}
	angle = 360 - angle
	if angle < 0 {
		angle = 180
	}
	return
}
